#pragma once
#include <string>
#include <map>
#include <tchar.h>
#ifdef _DEBUG
#define RE_NEW new(_NORMAL_BLOCK,__FILE__, __LINE__) 
#else
#define RE_NEW new
#endif

//CUSTOM STRING SYSTEM
//USED TO IMPROVE PERFORMERCE WHEN CMP strings. strcmp is considered the most expensive function in game development

//////////////////////////////////////////////////////////////
//WHEN AND HOW TO USE:
//When there is need to use strings as identity values. THis will speed up the cmp with around 60-70%,
//however initializing by string will be a slow opearation
//It is used for the event system to identify event types. 
//
// Initialization:
//RE_String(std::string("New Actor Event"));
// Listener, which cmp these strings to find out which piece of code care bout that event:
//Event.REstrEventType == EvtData_New_Actor::REstrEventType;
///////////////////////////////////////////////////////////////
class RE_StringTable;
typedef std::map< unsigned int, std::pair< std::string, unsigned int > > StringMap;
class RE_String
{
public:
	RE_String() { m_id = 0; }
	RE_String(const RE_String & str);
	RE_String(unsigned int id);
	RE_String(const std::string & str);
	RE_String(const std::wstring & str);
	RE_String(const TCHAR* const str);
	RE_String(char * c_str);
	~RE_String();
	unsigned int GetId() { return m_id; }
	const char * const c_str() const; // WARNING: SHOUD NOT BE MODIFIED DIRECTLY, THIS IS FOR FAST READ ONLY ACCESS
	bool SetString(std::string & str);

	//TODO: impl operato overloads;
	//bool operator==(RE_String str);
	bool operator==(const RE_String & str) const;
	bool operator<(const RE_String & str) const;
	RE_String & operator=(RE_String &str);
	//operator int(); // "get" the int opearators//Not needed after overloading operator<
private:
	unsigned int m_id;
#ifdef _DEBUG
#ifdef _TESTMODE
	std::string str_;
#endif
#endif
	
};
class RE_StringFactory
{
public:
	RE_StringFactory() : m_last_id(0), m_free_ids(0) { }
	~RE_StringFactory() {}

	unsigned int CreateStringId(); // called when a RE_NEW string is introduced.
	void SetLastId(unsigned int id);
	void AddFreeId() { ++m_free_ids; }
	void SubFreeId() { --m_free_ids; }
private:
	unsigned int m_last_id;
	unsigned int m_free_ids;
};
class RE_StringTable
{
public:
	friend RE_StringFactory;
	RE_StringTable();
	~RE_StringTable();

	static RE_StringTable * Get();//THIS Instance
	static std::tr1::shared_ptr<RE_StringTable>* GetPtr();
	unsigned int GetIdByString(const std::string & str);
	unsigned int ValidateId(unsigned int id);
	const std::string * GetStringById(unsigned int id); // shoud care when editing this

	void AddReference(const unsigned int id);
	void SubReference(const unsigned int id);

	void ReleaseStrings();
private:
	RE_StringFactory * GetFactory();

	std::tr1::shared_ptr<RE_StringFactory> m_pFactory;

protected:
	StringMap m_Strings;
};